package com.ll.studentservice.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ll.commonUtils.R;
import com.ll.servicebase.exceptionhandler.LLException;
import com.ll.studentservice.entity.EduKeInfo;
import com.ll.studentservice.entity.EduSign;
import com.ll.studentservice.entity.EduStudent;
import com.ll.studentservice.entity.vo.*;
import com.ll.studentservice.service.EduSignService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author ll
 * @since 2020-11-26
 */
@Api(description = "考勤API") //swagger界面提示
@RestController
@RequestMapping("/studentservice/sign")
public class EduSignController {

    @Autowired
    private EduSignService eduSignService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Test
    public void test() {
        LocalDateTime nowDateTime = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println(dateTimeFormatter.format(nowDateTime));
        LocalTime parse = LocalTime.parse("08:10:00");
        LocalTime parse1 = LocalTime.parse("08:55:00");
        boolean before = parse.isBefore(parse1);
        System.out.println(before);
        System.out.println(parse1.minusMinutes(5));
        LocalTime oneCourseStartTimeMinus10 = LocalTime.parse("08:55:00").minusMinutes(10);
        System.out.println(oneCourseStartTimeMinus10);
    }


    //教师发布考勤
    @ApiOperation(value = "教师发布考勤") //swagger界面提示
    @PostMapping("teacherSendSign")
    public R sendSignWithCodeByPost(@RequestBody TeacherSendSignWithCodeVo teacherSendSignWithCodeVo){

        //获取签到参数
        String classId = teacherSendSignWithCodeVo.getClassId();
        String teacherId = teacherSendSignWithCodeVo.getTeacherId();
        long time = teacherSendSignWithCodeVo.getTime();
        String code = teacherSendSignWithCodeVo.getCode();
        String whySign = teacherSendSignWithCodeVo.getWhySign();

        if (StringUtils.isEmpty(classId)){
            throw new LLException(20001, "班级Id为空");
        }

        if (StringUtils.isEmpty(teacherId)){
            throw new LLException(20001, "教师Id为空");
        }

        if (StringUtils.isEmpty(time)){
            throw new LLException(20001, "签到码有效期为空");
        }

        if (time <= 0){
            throw new LLException(20001, "签到码有效期必须大于0分钟");
        }

        //判断签到码是否为空
        if (!StringUtils.isEmpty(code)){
            //将传过来的签到码,放到redis里面
            //设置有效时间为传过来的time,以分钟为单位
            try {
                redisTemplate.opsForValue().set("signCode", code, time, TimeUnit.MINUTES);
            }catch (Exception e){
                e.printStackTrace();
                throw new LLException(20001, "无法连接redis,可能是网络出现错误");
            }

        } else {
            throw new LLException(20001, "签到码为空");
        }

        //获取当前是第几周
        String nowWeek =  eduSignService.getNowWeek();
        if (StringUtils.isEmpty(nowWeek)){
            throw new LLException(20001, "获取周数失败");
        }

        //获取当前要进行第几节课的签到
        //one two three
        String keNumber = eduSignService.getNoCourse();
        if (StringUtils.isEmpty(keNumber)){
            throw new LLException(20001, "当前时间没有可以进行发布签到的课程(时间早于08:00或者晚于21:10或者当前时间距离上课时间大于10分钟)");
        }

        //获取将要进行签到课程的id(ke_info_id)
        String keInfoId = eduSignService.getKeInfoId(classId);
        if (StringUtils.isEmpty(keInfoId)){
            throw new LLException(20001, "当前时间没有可以进行发布签到的课程(该班级当前时间不需要上课)");
        }

        //以班级为入口,查询出所有需要签到的学生(List<Student>)
        List<EduStudent> eduStudentList = eduSignService.getAllStudents(classId);

        System.out.println("===========EduSignController==========");
        System.out.println("根据班级id查询出来的所有学生");
        System.out.println(eduStudentList);

        //进行数据转换(查询出来的是student类,插入签到表的是sign类)
        List<EduSign> signList = new ArrayList<>();
        //遍历每个学生对象,并将学生id和学生班级id赋值给sign对象
        for (EduStudent eduStudent : eduStudentList) {
            EduSign eduSign = new EduSign();
            eduSign.setStudentId(eduStudent.getId());
            eduSign.setTeacherId(teacherId);
            eduSign.setClassId(eduStudent.getClassId());
            eduSign.setKeNumber(keNumber);
            eduSign.setKeInfoId(keInfoId);
            eduSign.setWhySign(whySign);
            eduSign.setSignDate(LocalDate.now());
            eduSign.setWeek(nowWeek);
            //没有设置是否签到,数据库默认是未签到
            signList.add(eduSign);
        }

        boolean b = eduSignService.saveBatch(signList);

        if (b){
            return R.ok().message("第" +  keNumber + "节课的考勤任务发布成功!" + "请在" + time + "分钟内完成签到");
        }else {
            return R.error().message("发布签到失败");
        }
    }


    //获取某个班将要签到的课程信息
    @GetMapping("getLaterSignCourseInfo/{classId}")
    @ApiOperation(value = "获取某个班将要签到的课程信息") //swagger界面提示
    public R getLaterSignCourseInfo(@PathVariable String classId){

        EduKeInfo eduKeInfo = eduSignService.findLaterSignCourseInfo(classId);

        if (StringUtils.isEmpty(eduKeInfo)){
            return R.error().message("当前时间已经没有到进行签到的课程了");
        } else {
            return R.ok().data("eduKe", eduKeInfo);
        }
    }


    //学生进行签到
    @ApiOperation(value = "学生通过签到码进行签到") //swagger界面提示
    @PostMapping("/studentSignByCode")
    public R studentSignByCode(@RequestBody StudentSignWithCodeVo studentSignWithCodeVo){

        String studentId = studentSignWithCodeVo.getStudentId();
        String code = studentSignWithCodeVo.getCode();

        //1.从redis中取验证码
        String signCode = redisTemplate.opsForValue().get("signCode");

        //如果不能从redis获取签到码,可以判断此时的签到已超过规定时间
        if (StringUtils.isEmpty(signCode)){
            return R.error().message("超过指定时间未签到");
        }

        //判断学生输入的签到码是否为空
        if (StringUtils.isEmpty(code)){
            return R.error().message("签到码为空");
        }

        //判断学生输入的签到码和从redis中获取的是否一致
        if (!code.equals(signCode)){
            return R.error().message("签到码错误");
        }

        //获取当前要进行第几节课的签到
        //one two three
        String keNumber = eduSignService.getNoCourse();
        if (StringUtils.isEmpty(keNumber)){
            throw new LLException(20001, "当前时间没有可以进行签到的课程keNumber");
        }


        //优化:判断学生是否签到过
        //待续

        //通过studentId,改变学生签到状态
        QueryWrapper<EduSign> wrapper = new QueryWrapper<>();
        wrapper.eq("student_id", studentId);
        wrapper.eq("ke_number", keNumber);
        //当老师多次发布签到,默认对最新的考勤请求进行签到
        wrapper.orderByDesc("gmt_create");

        EduSign eduSign = eduSignService.getOne(wrapper);

        //改变签到状态
        eduSign.setIsSign("1");
        //设置签到时间
        eduSign.setSignTime(LocalTime.now());
        boolean b = eduSignService.updateById(eduSign);

        return b ? R.ok().message("签到成功") : R.error().message("签到失败");
    }

    //学生自动进行签到
    @ApiOperation(value = "学生自动进行签到,测试,未完成") //swagger界面提示
    @GetMapping("/studentAutoSign/{studentId}")
    public R studentAutoSign(@PathVariable String studentId){
        EduSign eduSign = new EduSign();
//        eduSign.set

        return R.ok();
    }


    //查询某班指定日期指定第几节课所有未签到的学生
    @ApiOperation(value = "查询某班指定日期指定第几节课所有未签到的学生") //swagger界面提示
    @PostMapping("getAllNoSignStudent")
    public R getAllNoSignStudent(@RequestBody SignGetAllNOSignStudent signGetAllNOSignStudent){

        List<EduNoSignStudentInfo> studentInfos = eduSignService.getAllNoSign(signGetAllNOSignStudent);
        //未签到学生数量
        int size = studentInfos.size();

        return R.ok().data("total", size).data("AllNoSignStudent", studentInfos);
    }

    //查询某班指定日期指定第几节课所有已签到的学生
    @ApiOperation(value = "查询某班指定日期指定第几节课所有已签到的学生") //swagger界面提示
    @PostMapping("getAllSignStudent")
    public R getAllSignStudent(@RequestBody SignGetAllNOSignStudent signGetAllNOSignStudent){

        List<EduSignStudentInfo> studentInfos = eduSignService.getAllSign(signGetAllNOSignStudent);
        //已签到学生数量
        int size = studentInfos.size();

        return R.ok().data("total", size).data("AllSignStudent", studentInfos);
    }

    //查询某班今天第几节课所有已签到的学生
    @ApiOperation(value = "查询某班今天第几节课所有已签到的学生") //swagger界面提示
    @PostMapping("getAllSignStudentByToday")
    public R getAllSignStudentByToday(@RequestBody SignGetSignStudentByTodayVo SignGetSignStudentByTodayVo){

        List<EduSignStudentInfo> studentInfos = eduSignService.getAllSignByToday(SignGetSignStudentByTodayVo);
        //已签到学生数量
        int size = studentInfos.size();

        return R.ok().data("total", size).data("AllSignStudent", studentInfos);
    }

    //查询某班今天第几节课所有未签到的学生
    @ApiOperation(value = "查询某班今天第几节课所有未签到的学生") //swagger界面提示
    @PostMapping("getAllNoSignStudentByToday")
    public R getAllNoSignStudentByToday(@RequestBody SignGetSignStudentByTodayVo SignGetSignStudentByTodayVo){

        List<EduNoSignStudentInfo> studentInfos = eduSignService.getAllNoSignByToday(SignGetSignStudentByTodayVo);
        //已签到学生数量
        int size = studentInfos.size();

        return R.ok().data("total", size).data("AllNoSignStudent", studentInfos);
    }

    //修改某位学生某节课的考勤信息(指定日期指定第几节课)
    @ApiOperation(value = "修改某位学生某节课的考勤信息(指定学生Id指定日期指定第几节课指定考勤状态(签到状态(0未签到(旷课), 1已签到(出勤), 2迟到, 3请假)))") //swagger界面提示
    @PostMapping("updateOneStudentSignInfo")
    public R updateOneStudentSignInfo(@ApiParam(name = "SignUpdateOneStudentSignInfo", value = "参数", required = true)
                                          @RequestBody SignUpdateOneStudentSignInfo signUpdateOneStudentSignInfo){
        boolean update =  eduSignService.UpdateOneStudentSignInfo(signUpdateOneStudentSignInfo);
        return update ? R.ok().message("修改成功") : R.error().message("修改失败");

    }

    //查询某位学生某天某一节课的考勤信息(指定学生Id指定日期指定第几节课)
    @ApiOperation(value = "查询某位学生某天某一节课的考勤信息(指定学生Id指定日期指定第几节课)") //swagger界面提示
    @PostMapping("findOneStudentSignInfo")
    public R findOneStudentSignInfo(@ApiParam(name = "signUpdateOneStudentSignInfo", value = "参数", required = true)
                                      @RequestBody SignGetOneStudentSignInfoVo signGetOneStudentSignInfoVo){
        SignOneStudentSignInfoVo signOneStudentSignInfoVo = eduSignService.GetOneStudentSignInfo(signGetOneStudentSignInfoVo);
        if (StringUtils.isEmpty(signOneStudentSignInfoVo)){
            return R.error().message("查询失败");
        } else {
            return R.ok().data("studentInfo", signOneStudentSignInfoVo);
        }
    }

    //查询某位学生某一天的考勤信息(指定学生Id指定日期)
    @ApiOperation(value = "查询某位学生某一天的考勤信息(指定学生Id指定日期)") //swagger界面提示
    @PostMapping("findStudentSignInfoByOneDay")
    public R findStudentSignInfoByOneDay(@ApiParam(name = "signGetStudentSignInfoByOneDayVo", value = "参数", required = true)
                                    @RequestBody SignGetStudentSignInfoByOneDayVo signGetStudentSignInfoByOneDayVo){
        SignStudentSignInfoByOneDayVo signStudentSignInfoByOneDayVo = eduSignService.getStudentSignInfoByOneDay(signGetStudentSignInfoByOneDayVo);
        if (StringUtils.isEmpty(signStudentSignInfoByOneDayVo)){
            return R.error().message("查询失败");
        } else {
            return R.ok().data("提示","successCount:出勤次数 truantCount:旷课次数 lateCount:迟到次数 statusAndKe:请假次数").data("studentSignInfo", signStudentSignInfoByOneDayVo);
        }
    }

    //查询某班某一天的考勤信息(指定班级Id指定日期)
    @ApiOperation(value = "查询某班某一天的考勤信息(指定班级Id指定日期)") //swagger界面提示
    @PostMapping("findClassSignInfoByOneDay")
    public R findClassSignInfoByOneDay(@ApiParam(name = "signGetClassSignInfoByOneDayVo", value = "参数", required = true)
                                           @RequestBody SignGetClassSignInfoByOneDayVo signGetClassSignInfoByOneDayVo){

        SignClassInfoByOneDayVo signClassInfoByOneDayVo = eduSignService.GetClassSignInfoByOneDay(signGetClassSignInfoByOneDayVo);
        if (StringUtils.isEmpty(signClassInfoByOneDayVo)){
            return R.error().message("查询失败");
        } else {
            return R.ok().data("classSignInfo", signClassInfoByOneDayVo);
        }
    }

    //查询某学生一周的的考勤信息(指定学生Id指定第几周)
    @ApiOperation(value = "查询某学生一周的的考勤信息(指定学生Id指定第几周)") //swagger界面提示
    @PostMapping("findStudentSignInfoByWeek")
    public R findStudentSignInfoByWeek(@ApiParam(name = "signStudentSignInfoByWeekVo", value = "参数", required = true)
                                           @RequestBody SignStudentSignInfoByWeekVo signStudentSignInfoByWeekVo){

        SignStudentSignInfoByOneWeekVo signStudentSignInfoByOneWeekVo = eduSignService.GetStudentSignInfoByWeek(signStudentSignInfoByWeekVo);

        if (StringUtils.isEmpty(signStudentSignInfoByOneWeekVo)){
            return R.error().message("信息为空或者参数错误");
        }

        return R.ok().data("oneWeekStudentSignInfo", signStudentSignInfoByOneWeekVo);
    }

    //查询某班一周的的考勤信息(指定班级Id指定第几周)
    @ApiOperation(value = "查询某班一周的的考勤信息(指定班级Id指定第几周)") //swagger界面提示
    @PostMapping("findClassSignInfoByWeek")
    public R findClassSignInfoByWeek(@ApiParam(name = "signClassSignInfoByWeekVo", value = "参数", required = true)
                                         @RequestBody SignClassSignInfoByWeekVo signClassSignInfoByWeekVo){

        SignClassSignInfoByOneWeekVo signClassSignInfoByOneWeekVo = eduSignService.getClassSignInfoByWeek(signClassSignInfoByWeekVo);

        if (StringUtils.isEmpty(signClassSignInfoByOneWeekVo)){
            return R.error().message("信息为空或者参数错误");
        }

        //获取某个班的学生人数
        int total = eduSignService.getClassStudentTotal(signClassSignInfoByWeekVo.getClassId());

        return R.ok().data("total", total).data("oneWeekClassSignInfo", signClassSignInfoByOneWeekVo);
    }

    //查询某专业下所有班级某天的的考勤信息(指定专业Id指定日期)
    @ApiOperation(value = "查询某专业下所有班级某天的的考勤信息(指定专业Id指定日期)") //swagger界面提示
    @PostMapping("findProfessionSignByDay")
    public R findProfessionSignByDay(@ApiParam(name = "signProfessioByDayVo", value = "参数", required = true)
                                         @RequestBody SignProfessioByDayVo signProfessioByDayVo){

        SignProfessionSignInfoByDayVo signProfessionSignInfoByDayVo = eduSignService.GetProfessionSignByDay(signProfessioByDayVo);

        return R.ok().data("professionSignInfo", signProfessionSignInfoByDayVo);
    }

    //查询某年级某专业某天的考勤信息(指定年级Id指定专业Id指定要查询的日期)
    @ApiOperation(value = "查询某年级某专业某天的考勤信息(指定年级Id指定专业Id指定要查询的日期)") //swagger界面提示
    @PostMapping("findEqualGradeDisaffinityProfessionSignByDay")
    public R findEqualGradeDisaffinityProfessionSignByDay(@ApiParam(name = "signFindGradeAndProfessionByDayVo", value = "参数", required = true)
                                                              @RequestBody SignFindGradeAndProfessionByDayVo signFindGradeAndProfessionByDayVo){
        SignProfessionSignInfoByDayVo signProfessionSignInfoByDayVo = eduSignService.getEqualGradeDisaffinityProfessionSignByDay(signFindGradeAndProfessionByDayVo);

        return R.ok().data("info", signProfessionSignInfoByDayVo);
    }

    //查询某年级某专业某周的考勤信息(指定年级Id指定专业Id指定要查询的日期)
    @ApiOperation(value = "查询某年级某专业某周的考勤信息(指定年级Id指定专业Id指定要查询的日期)") //swagger界面提示
    @PostMapping("findGradeProfessionSignByWeek")
    public R findGradeProfessionSignByWeek(@ApiParam(name = "signFindGradeAndProfessionByWeekVo", value = "参数", required = true)
                                                          @RequestBody SignFindGradeAndProfessionByWeekVo signFindGradeAndProfessionByWeekVo){
        SignProfessionSignInfoByDayVo signProfessionSignInfoByDayVo = eduSignService.getGradeProfessionSignByWeek(signFindGradeAndProfessionByWeekVo);

        return R.ok().data("info", signProfessionSignInfoByDayVo);
    }




    //根据signId,查询单个考勤信息
    @ApiOperation(value = "根据signId,查询单个考勤信息(signId是签到表的主键)") //swagger界面提示
    @PostMapping("findOneSignInfoBySignId/{signId}")
    public R findOneSignInfoBySignId(@PathVariable String signId){
        EduSign eduSign = eduSignService.getById(signId);
        if (StringUtils.isEmpty(eduSign)){
            return R.error().message("查询失败(signId错误或数据库中没有相应的信息)");
        } else {
            return R.ok().data("signInfo", eduSign);
        }

    }

    //给某个学生某节课评分
    @ApiOperation(value = "给某个学生某节课评分") //swagger界面提示
    @PostMapping("addKeScore")
    public R addKeScore(@RequestBody KeScoreVO keScoreVO){
        boolean flag = eduSignService.addKeSocreWithStudent(keScoreVO);

        return flag ? R.ok().message("添加成功") : R.error().message("添加失败");
    }


    //查询所有已经签到的学生
//    @ApiOperation(value = "查询所有已经签到的学生") //swagger界面提示
//    @GetMapping("getAllSignStudent/{classId}")
//    public R getAllSignStudent(@PathVariable("classId") String classId){
//
//        List<EduSignStudentInfo> studentInfos = eduSignService.getAllSign(classId);
//
//        return R.ok().data("AllSignStudent", studentInfos);
//    }
}

